﻿using System;
using System.Collections.Generic;
using Framework;
using RecipeModule;
using UnityEngine;
using UnityEngine.UI;

namespace View
{
    public class EditRecipeView : ViewProxy
    {
        private ClickTrigger _triggerClose;
        private ClickTrigger _triggerSelect;
        private ClickTrigger _triggerConfirm;

        private Toggle[] _toggleDishTypes;
        private EditRecipeTab[] _tabDishTypes;
        
        private Text _textCalories;
        private Image _imageProgress;
        private Text _textSelectNum;

        private int _recipeId;
        private Recipe _recipe;
        private DishType _currentDishType;

        private EditRecipePage[] _pages;

        public void SetRecipeId(int recipeId)
        {
            _recipeId = recipeId;
            _recipe = RecipeManager.instance.CloneRecipe(_recipeId);
            Update();
        }
        
        protected override void SetupView()
        {
            LoadRes("Views/Recipe/EditRecipeView");
        }

        protected override void OnInit()
        {
            _triggerClose = ClickTrigger.Get(_transform.Find("Button_Close"));
            _triggerClose.AddClickListener(OnCloseClick);
            
            _triggerSelect = ClickTrigger.Get(_transform.Find("Button_Select"));
            _triggerSelect.AddClickListener(OnSelectClick);
            
            _triggerConfirm = ClickTrigger.Get(_transform.Find("Button_Confirm"));
            _triggerConfirm.AddClickListener(OnConfirmClick);
            
            _toggleDishTypes = new Toggle[4];
            _tabDishTypes = new EditRecipeTab[4];
            for (int i = 0; i < 4; ++i)
            {
                Transform transform = _transform.Find("DishType/Toggle_" + (i + 1));
                Toggle toggle = transform.GetComponent<Toggle>();
                toggle.onValueChanged.AddListener(OnDishTypeChanged);
                _toggleDishTypes[i] = toggle;
                
                EditRecipeTab tab = new EditRecipeTab(transform.gameObject, (DishType)i);
                _tabDishTypes[i] = tab;
            }
            _currentDishType = DishType.Fiber;

            _textCalories = _transform.Find("Text_Calories").GetComponent<Text>();
            _imageProgress = _transform.Find("Image_Progress").GetComponent<Image>();
            
            _textSelectNum = _transform.Find("Button_Select/Text_Num").GetComponent<Text>();

            GameObject pagePrefab = _transform.Find("Pages/Page").gameObject;
            _pages = new EditRecipePage[4];
            for (int i = 0; i < 4; ++i)
            {
                EditRecipePage page = new EditRecipePage(GameObject.Instantiate(pagePrefab), (DishType)i);
                page.GetTransform().SetParent(pagePrefab.transform.parent, false);
                page.DishClickEvent += OnDishClick;
                _pages[i] = page;
            }
            pagePrefab.SetActive(false);
        }

        protected override void OnDispose()
        {
            for (var i = 0; i < _pages.Length; i++)
            {
                _pages[i].Dispose();
            }
            _pages = null;
        }

        private void Update()
        {
            for (var i = 0; i < _toggleDishTypes.Length; i++)
            {
                _toggleDishTypes[i].isOn = i == (int)_currentDishType;
            }
            for (var i = 0; i < _pages.Length; i++)
            {
                _pages[i].SetActive(i == (int)_currentDishType);
                _pages[i].SetRecipe(_recipe);
            }
            for (var i = 0; i < _tabDishTypes.Length; i++)
            {
                _tabDishTypes[i].SetRecipe(_recipe);
            }

            _textCalories.text = "0";
            _imageProgress.fillAmount = 0;
            _textSelectNum.text = "0";

            if (_recipe != null)
            {
                float totalCalories = 0f;
                
                for (var i = 0; i < _recipe.listDish.Count; i++)
                {
                    RecipeDish recipeDish = _recipe.listDish[i];
                    Dish dish = DishConfig.GetDish(recipeDish.dishId);
                    totalCalories += dish.calories * recipeDish.count;
                }

                _textCalories.text = totalCalories.ToString();
                _imageProgress.fillAmount = totalCalories / 10000f;

                _textSelectNum.text = _recipe.listDish.Count.ToString();
            }
        }

        private void OnDishClick(Dish dish)
        {
            if (_recipe.AddDish(dish))
            {
                Update();
            }
        }
        
        private void OnDishTypeChanged(bool value)
        {
            DishType dishType = _currentDishType;
            for (var i = 0; i < _toggleDishTypes.Length; i++)
            {
                if (_toggleDishTypes[i].isOn)
                {
                    dishType = (DishType) i;
                    break;
                }
            }
            _currentDishType = dishType;
            Update();
        }

        private void OnCloseClick(params object[] args)
        {
            Close();
        }
        
        private void OnSelectClick(params object[] args)
        {
            
        }
        
        private void OnConfirmClick(params object[] args)
        {
            RecipeManager.instance.ReplaceRecipe(_recipe);
            Close();
        }

        private class EditRecipePage
        {
            public event Action<Dish> DishClickEvent;
            
            private GameObject _gameObject;
            private RectTransform _transform;

            private DishType _dishType;

            private EditRecipeGrid[] _grids;
            
            public EditRecipePage(GameObject gameObject, DishType dishType)
            {
                _gameObject = gameObject;
                _transform = (RectTransform) _gameObject.transform;
                _dishType = dishType;

                GameObject gridPrefab = _transform.Find("Grid").gameObject;
                List<Dish> listDish = new List<Dish>();
                for (var i = 0; i < DishConfig.Dishes.Length; i++)
                {
                    Dish dish = DishConfig.Dishes[i];
                    if (dish.dishType == dishType)
                    {
                        listDish.Add(dish);
                    }
                }
                
                _grids = new EditRecipeGrid[listDish.Count];
                for (var i = 0; i < listDish.Count; i++)
                {
                    Dish dish = listDish[i];
                    GameObject goDish = GameObject.Instantiate(gridPrefab);
                    EditRecipeGrid grid = new EditRecipeGrid(goDish, dish);
                    grid.AddTo(gridPrefab.transform.parent);
                    ClickTrigger trigger = ClickTrigger.Get(grid.GetTransform());
                    trigger.AddClickListener(OnGridClick, dish);
                    _grids[i] = grid;
                }
                gridPrefab.SetActive(false);
            }

            public void Dispose()
            {
                for (var i = 0; i < _grids.Length; i++)
                {
                    _grids[i].Dispose();
                }
                _grids = null;
                GameObject.Destroy(_gameObject);
            }

            public RectTransform GetTransform()
            {
                return _transform;
            }
            
            public void SetActive(bool value)
            {
                _gameObject.SetActive(value);
            }

            public void SetRecipe(Recipe recipe)
            {
                for (var i = 0; i < _grids.Length; i++)
                {
                    _grids[i].SetRecipe(recipe);
                }
            }

            private void OnGridClick(params object[] args)
            {
                Dish dish = (Dish) args[0];
                if (DishClickEvent != null)
                {
                    DishClickEvent(dish);
                }
            }
        }

        private class EditRecipeTab
        {
            private GameObject _gameObject;
            private RectTransform _transform;
            private DishType _dishType;
            private Text _textNum;
            private GameObject _goNum;

            public EditRecipeTab(GameObject gameObject, DishType dishType)
            {
                _gameObject = gameObject;
                _transform = (RectTransform) _gameObject.transform;
                _dishType = dishType;
                _textNum = _transform.Find("Text_Num").GetComponent<Text>();
                _goNum = _transform.Find("Image").gameObject;
            }
            
            public void SetRecipe(Recipe recipe)
            {
                _goNum.SetActive(false);
                _textNum.text = string.Empty;
                if (recipe != null)
                {
                    int totalCount = 0;
                    for (var i1 = 0; i1 < recipe.listDish.Count; i1++)
                    {
                        RecipeDish recipeDish = recipe.listDish[i1];
                        Dish dish = DishConfig.GetDish(recipeDish.dishId);
                        if (dish.dishType == _dishType)
                        {
                            totalCount += recipeDish.count;
                        }
                    }
                    if (totalCount > 0)
                    {
                        _goNum.SetActive(true);
                        _textNum.text = "x" + totalCount;
                    }
                }
            }
        }

        private class EditRecipeGrid
        {
            private GameObject _gameObject;
            private RectTransform _transform;
            private Dish _dish;
            private DishIconProxy _iconProxy;
            private Text _textNum;
            private Text _textCalories;
            private Text _textPrice;
            private GameObject _goNum;
            
            public EditRecipeGrid(GameObject gameObject, Dish dish)
            {
                _gameObject = gameObject;
                _transform = (RectTransform) _gameObject.transform;

                _dish = dish;
                
                _iconProxy = new DishIconProxy();
                _iconProxy.AddTo(_transform.Find("Icon"));
                _iconProxy.SetIconId(_dish.id);

                _goNum = _transform.Find("Image_Num").gameObject;
                _textNum = _transform.Find("Text_Num").GetComponent<Text>();
                _textCalories = _transform.Find("Text_Calories").GetComponent<Text>();
                _textPrice = _transform.Find("Text_Price").GetComponent<Text>();
                
                _textPrice.text = _dish.price.ToString();
                _textCalories.text = _dish.calories.ToString();
            }

            public void Dispose()
            {
                GameObject.Destroy(_gameObject);
            }

            public void AddTo(Transform parent)
            {
                _transform.SetParent(parent, false);
            }

            public RectTransform GetTransform()
            {
                return _transform;
            }

            public void SetRecipe(Recipe recipe)
            {
                _goNum.SetActive(false);
                _textNum.text = string.Empty;
                if (recipe != null)
                {
                    for (var i = 0; i < recipe.listDish.Count; i++)
                    {
                        RecipeDish recipeDish = recipe.listDish[i];
                        if (recipeDish.dishId == _dish.id)
                        {
                            _goNum.SetActive(true);
                            _textNum.text = "x" + recipeDish.count;
                            break;
                        }
                    }
                }
            }
        }
    }
}